package com.jphoebe.plugin.mybatis.form;

import cn.hutool.core.util.ObjectUtil;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileChooser.FileChooser;
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.project.ProjectUtil;
import com.intellij.openapi.ui.popup.JBPopupFactory;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiDirectory;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiManager;
import com.intellij.psi.impl.source.xml.XmlFileImpl;
import com.jphoebe.plugin.mybatis.bean.setting.ProjectSetting;
import com.jphoebe.plugin.mybatis.service.EditorService;
import com.jphoebe.plugin.mybatis.service.setting.ProjectSettingService;
import com.jphoebe.plugin.mybatis.template.MybatisFileTemplateDescriptorFactory;
import com.jphoebe.plugin.mybatis.utils.jetbrain.JetbrainMapperUtil;
import lombok.Setter;
import org.apache.commons.lang3.StringUtils;

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.Collection;
import java.util.HashMap;
import java.util.Properties;


public class CreateMybatisXmlFileForm extends JDialog {
    private JPanel contentPane;
    private JButton buttonOK;
    private JButton buttonCancel;
    private JList dirPathChooser;
    private JButton chooseMoreBtn;

    /*** 项目设置 */
    private ProjectSettingService projectSettingService;
    private Project project;
    Collection<PsiDirectory> directories;
    HashMap<String, PsiDirectory> stringPsiDirectoryHashMap;

    /*** 正在编辑的文件信息 */
    @Setter
    private Editor editor;
    @Setter
    private PsiClass psiClass;

    public CreateMybatisXmlFileForm() {
        project = ProjectUtil.guessCurrentProject(this.contentPane);
        projectSettingService = ProjectSettingService.getInstance(project);

        setContentPane(contentPane);
        setModal(true);
        getRootPane().setDefaultButton(buttonOK);
        setTitle("Select target folder");

        // 弹出框居中
        Dimension screenSize = Toolkit.getDefaultToolkit().getScreenSize();
        int frameWidth = this.getPreferredSize().width;
        int frameHeight = this.getPreferredSize().height;
        this.setLocation((screenSize.width - frameWidth) / 2, (screenSize.height - frameHeight) / 2);
//        this.setResizable(false);

        // 显示历史mapper xml文件目录
        stringPsiDirectoryHashMap = new HashMap<>();
        ProjectSetting projectSetting = projectSettingService.getState();
        directories = JetbrainMapperUtil.findMapperDirectories(project);
        DefaultListModel listModel = new DefaultListModel();
        for (PsiDirectory directory : directories) {
            String filePath = directory.getVirtualFile().getPath();
            if(StringUtils.isNotEmpty(projectSetting.getLastCreateMybatisXmlPath()) && projectSetting.getLastCreateMybatisXmlPath().equals(filePath)){
                listModel.insertElementAt(filePath, 0);
            }else{
                listModel.addElement(filePath);
            }
            stringPsiDirectoryHashMap.put(filePath, directory);
        }
        dirPathChooser.setModel(listModel);
        if(!directories.isEmpty()){
            dirPathChooser.setSelectedIndex(0);
        }

        // 绑定添加按钮为选择文件夹
        chooseMoreBtn.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                showFileDialog();
            }
        });

        buttonOK.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                onOK();
            }
        });

        buttonCancel.addActionListener(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                onCancel();
            }
        });

        // call onCancel() when cross is clicked
        setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                onCancel();
            }
        });

        // call onCancel() on ESCAPE
        contentPane.registerKeyboardAction(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                onCancel();
            }
        }, KeyStroke.getKeyStroke(KeyEvent.VK_ESCAPE, 0), JComponent.WHEN_ANCESTOR_OF_FOCUSED_COMPONENT);

    }

    private void onOK() {
        Object selectedValue = dirPathChooser.getSelectedValue();
        if (ObjectUtil.isNotNull(selectedValue)) {
            String selectedPath = (String) selectedValue;
            // 创建模板
            try {
                PsiDirectory psiDirectory = stringPsiDirectoryHashMap.get(selectedPath);
                Properties properties = new Properties();
                properties.setProperty("NAMESPACE", psiClass.getQualifiedName());
                PsiElement psiFile = JetbrainMapperUtil.createMapperFromFileTemplate(MybatisFileTemplateDescriptorFactory.MYBATIS_MAPPER_XML_TEMPLATE,
                        psiClass.getName(), psiDirectory, properties);
                // 光标地址
                TextRange textRange = ((XmlFileImpl) psiFile).getDocument().getRootTag().getValue().getTextRange();
                int offset = (textRange.getStartOffset()+textRange.getEndOffset())/2;
                EditorService.getInstance(psiClass.getProject()).scrollTo(psiFile, offset);
            } catch (Exception e) {
                JBPopupFactory.getInstance().createMessage("create mapper xml failed: " + e.getMessage()).showInCenterOf(this.contentPane);
            }
            dispose();
        }
    }

    private void onCancel() {
        // add your code here if necessary
        dispose();
    }

    // 显示文件夹选择框
    private void showFileDialog() {
        VirtualFile virtualFile = showSingleFolderSelectionDialog();
        if (null != virtualFile) {
            PsiDirectory directory = PsiManager.getInstance(project).findDirectory(virtualFile);
            if (null == directory) {
                return;
            }
            if (!directory.isWritable()) {
//                  HintManager.getInstance().showErrorHint(allEditors[1], "Target directory is not writable");
//                  ListPopup confirmation = JBPopupFactory.getInstance().createConfirmation("Target directory is not writable", null, 0);
//                  confirmation.showInCenterOf(this.contentPane);
                JBPopupFactory.getInstance().createMessage("Target directory is not writable").showInCenterOf(this.contentPane);
                return;
            }
            /// 添加路径
            String newPath = directory.getVirtualFile().getPath();
            ProjectSetting projectSetting = projectSettingService.getState();
            projectSetting.setLastCreateMybatisXmlPath(newPath);
            projectSettingService.loadState(projectSetting);
            DefaultListModel listModel = (DefaultListModel) dirPathChooser.getModel();
            boolean isExist = false;
            for (PsiDirectory psiDirectory : directories) {
                String path = psiDirectory.getVirtualFile().getPath();
                if(path.equals(newPath)){
                    isExist = true;
                    break;
                }
            }
            if(!isExist){
                listModel.insertElementAt(newPath, 0);
                dirPathChooser.setModel(listModel);
                dirPathChooser.setSelectedIndex(0);
                stringPsiDirectoryHashMap.put(newPath, directory);
            }else{
                int index = listModel.indexOf(newPath);
                dirPathChooser.setSelectedIndex(index);
            }

        }
    }

    private VirtualFile showSingleFolderSelectionDialog() {
        VirtualFile baseDir = project.getBaseDir();
        String title = "Select target folder";
        final FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFolderDescriptor();
        descriptor.setTitle(title);
        if (null != baseDir) {
            descriptor.setRoots(baseDir);
        }
        descriptor.setHideIgnored(true);
        descriptor.setShowFileSystemRoots(true);

        return FileChooser.chooseFile(descriptor, project, baseDir);
    }

    public static void main(String[] args) {
        CreateMybatisXmlFileForm dialog = new CreateMybatisXmlFileForm();
        dialog.pack();
        dialog.setVisible(true);
        System.exit(0);
    }
}
